package com.advertisementsystem.Servie.Impl;

import com.advertisementsystem.Dto.ChatMessageDTO;
import com.advertisementsystem.Mapper.AdNegotiationMapper;
import com.advertisementsystem.Mapper.ChatMessagesMapper;
import com.advertisementsystem.Mapper.ChatSessionsMapper;
import com.advertisementsystem.Mapper.OfflineMessagesMapper;
import com.advertisementsystem.MessageStatus;
import com.advertisementsystem.MessageType;
import com.advertisementsystem.Servie.ChatService;
import com.advertisementsystem.SessionStatus;
import com.advertisementsystem.entity.AdNegotiation;
import com.advertisementsystem.entity.ChatMessages;
import com.advertisementsystem.entity.ChatSessions;
import com.advertisementsystem.entity.OfflineMessages;
import com.advertisementsystem.handler.ChatWebSocketHandler;
import com.advertisementsystem.utils.RedisCache;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.UUID;

@Service
@Transactional
@Slf4j
public class ChatServiceImpl implements ChatService {

    @Autowired
    private ChatMessagesMapper chatMessageRepository;

    @Autowired
    private ChatSessionsMapper chatSessionRepository;

    @Autowired
    private OfflineMessagesMapper offlineMessageRepository;

    // 使用setter注入来避免循环依赖
    private ChatWebSocketHandler chatWebSocketHandler;

    @Autowired
    public void setChatWebSocketHandler(ChatWebSocketHandler chatWebSocketHandler) {
        this.chatWebSocketHandler = chatWebSocketHandler;
    }


    @Autowired
    private RedisCache redisCache;

    @Autowired
    private AdNegotiationMapper adNegotiationMapper;

    @Override
    public ChatMessages sendMessage(ChatMessageDTO messageDTO) {
        System.out.println("messageDTO = " + messageDTO);
        // 创建消息
        ChatMessages message = new ChatMessages();
        BeanUtils.copyProperties(messageDTO, message);
        message.setMessageId(UUID.randomUUID().toString());
        message.setStatus(String.valueOf(MessageStatus.SENT));
        message.setCreatedTime(LocalDateTime.now());
        message.setUpdatedTime(LocalDateTime.now());
        message.setMessageType(String.valueOf(messageDTO.getMessageType()));
        if (messageDTO.getMessageType() == MessageType.IMAGE)
        {
            message.setFileName(message.getFileName());
            message.setFileSize(Long.valueOf(messageDTO.getFileSize()));
            message.setFileUrl(messageDTO.getFileUrl());
        }

// 3. 获取或创建会话
        LambdaQueryWrapper<ChatSessions> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChatSessions::getNegotiationId, message.getNegotiationId());

        // ChatSessions session = chatSessionRepository.findByNegotiationId(message.getNegotiationId());
        ChatSessions session = chatSessionRepository.selectOne(queryWrapper);
        if (session == null)
        {
            createNewSession(message);
        }

        System.out.println("message = " + message);
        // 保存消息

        chatMessageRepository.insert(message);

        // 更新会话
        updateChatSession(message);

        // 检查接收者是否在线
        if (isUserOnline(message.getToUserId())) {
            // 存储离线消息
            chatWebSocketHandler.sendNotification(message.getToUserId(), messageDTO);
        }
        saveOfflineMessage(message);



        return message;
    }

    public List<ChatMessages> getMessageHistory(Long negotiationId) {
        LambdaQueryWrapper<ChatMessages> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChatMessages::getNegotiationId, negotiationId);
        queryWrapper.orderByAsc(ChatMessages::getCreatedTime);
        return chatMessageRepository.selectList(queryWrapper);
    }

    public void markMessageAsRead(String messageId) {
        LambdaUpdateWrapper<ChatMessages> Wrapper = new LambdaUpdateWrapper<>();
        Wrapper.eq(ChatMessages::getMessageId, messageId);
        Wrapper.set(ChatMessages::getStatus, MessageStatus.READ);
        chatMessageRepository.update(null, Wrapper);
    }

    public void recallMessage(String messageId, Long userId) {
        ChatMessages message = chatMessageRepository.selectById(messageId);

        if (!message.getFromUserId().equals(userId)) {
            throw new RuntimeException("No permission to recall this message");
        }

        if (ChronoUnit.MINUTES.between(message.getCreatedTime(), LocalDateTime.now()) > 2) {
            throw new RuntimeException("Cannot recall message after 2 minutes");
        }

        message.setStatus(String.valueOf(MessageStatus.RECALLED));
        message.setUpdatedTime(LocalDateTime.now());
        chatMessageRepository.insert(message);
    }

    private void updateChatSession(ChatMessages message) {

        LambdaQueryWrapper<ChatSessions> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChatSessions::getNegotiationId, message.getNegotiationId());

        // ChatSessions session = chatSessionRepository.findByNegotiationId(message.getNegotiationId());
        ChatSessions session = chatSessionRepository.selectOne(queryWrapper);

        session.setLastMessageId(message.getMessageId());

        session.setUpdatedTime(LocalDateTime.now());

        if (!message.getFromUserId().equals(session.getAdvertiserId())) {
            chatSessionRepository.incrementUnreadCount(session.getSessionId());
        }

        chatSessionRepository.updateById(session);
    }

    private void createNewSession(ChatMessages message) {
        // 1. 获取协商信息
        AdNegotiation negotiation = adNegotiationMapper.selectById(message.getNegotiationId());
        System.out.println(negotiation);
        if (negotiation == null) {
            throw new RuntimeException("协商信息不存在");
        }
        // 2. 创建新会话
        ChatSessions session = new ChatSessions();
//        Random random = new Random();
//        Long l = random.nextLong(1000);
        session.setNegotiationId(message.getNegotiationId());
        session.setAdvertiserId(negotiation.getAdvertiserId());
        session.setDeviceOwnerId(negotiation.getDeviceOwnerId());
        session.setLastMessageId(message.getMessageId());
        session.setStatus(SessionStatus.ACTIVE.name());
        session.setUnreadCount(0);
        session.setCreatedTime(LocalDateTime.now());
        session.setUpdatedTime(LocalDateTime.now());
        System.out.println(session+"0000000000000000");

        log.info("保存绘画");
        // 3. 保存会话
         int i = chatSessionRepository.insert(session);
         log.info(i+"插入成功");
    }

    private boolean isUserOnline(Long userId) {

        return redisCache.hasKey("online_users:" + userId);
    }

    private void saveOfflineMessage(ChatMessages message) {
        OfflineMessages offlineMessage = new OfflineMessages();
        offlineMessage.setMessageId(message.getMessageId());
        offlineMessage.setToUserId(message.getToUserId());
        offlineMessage.setCreatedTime(LocalDateTime.now());
        offlineMessageRepository.insert(offlineMessage);
    }
}
